package com.ioc.xml;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.util.List;

/**
 * @author xinwang
 * @date 2020/2/26 23:18
 * 自定义spring容器 xml  实现
 **/
public class ExtClassPathXmlApplicationContext {
    //xml文件路径
    private String xmlPath;

    public ExtClassPathXmlApplicationContext(String xmlPath) {
        this.xmlPath = xmlPath;
    }

    public Object getBean(String beanId) throws Exception {
        if (StringUtils.isEmpty(beanId)) {
            throw new Exception("beanId不能为空");
        }
        //调用获取所有子节点
        List<Element> elements = readerXml();
        if (elements == null || elements.isEmpty()) {
            throw new Exception("配装文件中没有配装bean的信息");
        }
        String className = findByElementClass(elements, beanId);
        if (StringUtils.isEmpty(className)){
            throw new Exception("该bean对象没有配置class地址");
        }
        //调用反射创建对象返回
        return newInstance(className);
    }

    /**
     * 获取上下文路径
     *
     * @param xmlPath xml文件路径
     * @return
     */
    public InputStream getResourceAsStream(String xmlPath) {
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(xmlPath);
        return inputStream;
    }

    /**
     * 获取所有子节点
     *
     * @return
     * @throws DocumentException
     */
    public List<Element> readerXml() throws DocumentException {
        SAXReader saxReader = new SAXReader();
        //读取xml
        Document document = saxReader.read(getResourceAsStream(xmlPath));
        //获取根节点
        Element rootElement = document.getRootElement();
        //获取所有子节点
        List<Element> elements = rootElement.elements();
        return elements;
    }

    /**
     * 获取到对应class 地址
     * @param elements  所有子节点
     * @param beanId    传入的要获取的class地址的id
     * @return
     */
    public String findByElementClass(List<Element> elements,String beanId){
        for (Element element : elements) {
            //获取当前子节点属性
            String xmlBeanId = element.attributeValue("id");
            if (StringUtils.isEmpty(xmlBeanId)) {
                continue;
            }
            //当前子节点id不为空
            if (xmlBeanId.equals(beanId)) {
                //返回获取到class属性 class地址
                return element.attributeValue("class");
            }
        }
        return null;
    }
    /**
     * 反射初始化对象
     *
     * @param className 要反射创建的class地址
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public Object newInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> classInfo = Class.forName(className);
        return classInfo.newInstance();
    }

}
